#!/usr/bin/python3

import sys
import librungame.util
import librungame.runner
import librungame.game.windows


def die(msg):
    print(msg, file=sys.stderr)
    sys.exit(1)


def run():
    sysInfo = librungame.util.SysInfo()
    game = librungame.game.windows.CallOfDuty2("/opt/call-of-duty2")
    runner = librungame.runner.Wine(verbose=2)
    with librungame.RunGame(sysInfo, "call-of-duty2", game, runner).context(edit_or_run=False) as rg:
        game.apply_fullscreen_or_windowed(True)
        rg.run("sp")


class ArgParser:

    progName = "call-of-duty2"

    class ParseError(Exception):
        pass

    @classmethod
    def print_help(cls):
        print('%s is the main entrance of game Beach Head 2002.' % (cls.progName))
        print('   Run the game:')
        print('       %s' % (cls.progName))
        print('   Config the game:')
        print('       %s -s                                           # Show game config' % (cls.progName))
        print('       %s -cg <on|off>                                 # Enable/disable initial anmiation' % (cls.progName))
        print('   List profiles:')
        print('       %s -l' % (cls.progName))
        print('   Inspect a profile:')
        print('       %s -i <profile>' % (cls.progName))
        print('   Export key mapping:')
        print('       %s -e <profile>' % (cls.progName))
        print('   Modify a profile:')
        print("       %s -N <new-name> <profile>                      # Change profile name" % (cls.progName))
        print("       %s -M <new-money> <profile>                     # Set money" % (cls.progName))
        print("       %s -B <new-bounty> -C <car-index> <profile>     # Set bounty" % (cls.progName))
        print('')

    @staticmethod
    def parseHelp():
        if sys.argv[1] == "-h" or sys.argv[1] == "--help":
            return DynObject()
        else:
            return None

    @classmethod
    def parseShow(cls):
        if sys.argv[1] != "-s":
            return None

        i = 1
        while i < len(sys.argv):
            if sys.argv[i] == "-s":
                i += 1
                continue
            break
        if i < len(sys.argv):
            raise cls.ParseError("Error: Redundant argument(s) found.")
        return DynObject()

    @classmethod
    def parseConfig(cls):
        if sys.argv[1] not in ["-cg"]:
            return None

        ret = DynObject()
        ret.cg = None

        i = 1
        bFound = False
        while i < len(sys.argv):
            if sys.argv[i] == "-cg":
                if ret.cg is not None:
                    raise cls.ParseError('Error: Multiple "-cg" arguments found.')
                if i + 1 >= len(sys.argv) or sys.argv[i + 1] not in ["on", "off"]:
                    raise cls.ParseError('Error: "on" or "off" must be specified after "-cg" argument.')
                ret.cg = sys.argv[i + 1]
                i += 2
                bFound = True
                continue
            break
        if i < len(sys.argv):
            raise cls.ParseError("Error: Redundant argument(s) found.")
        if not bFound:
            raise cls.ParseError("Error: No modify operation specified.")
        return ret

    @classmethod
    def parseList(cls):
        if sys.argv[1] != "-l":
            return None

        i = 1
        while i < len(sys.argv):
            if sys.argv[i] == "-l":
                i += 1
                continue
            break
        if i < len(sys.argv):
            raise cls.ParseError("Error: Redundant argument(s) found.")
        return DynObject()

    @classmethod
    def parseInspect(cls):
        if sys.argv[1] != "-i":
            return None

        ret = DynObject()
        ret.profile_name = None

        i = 1
        while i < len(sys.argv):
            if sys.argv[i] == "-i":
                i += 1
                continue
            if ret.profile_name is None:
                ret.profile_name = sys.argv[i]
                i += 1
                continue
            break
        if i < len(sys.argv):
            raise cls.ParseError("Error: Redundant argument(s) found.")
        if ret.profile_name is None:
            raise cls.ParseError("Error: No profile specified.")
        return ret

    @classmethod
    def parseExportKeyMapping(cls):
        if sys.argv[1] != "-e":
            return None

        ret = DynObject()
        ret.profile_name = None

        i = 1
        while i < len(sys.argv):
            if sys.argv[i] == "-e":
                i += 1
                continue
            if ret.profile_name is None:
                ret.profile_name = sys.argv[i]
                i += 1
                continue
            break
        if i < len(sys.argv):
            raise cls.ParseError("Error: Redundant argument(s) found.")
        if ret.profile_name is None:
            raise cls.ParseError("Error: No profile specified.")
        return ret

    @classmethod
    def parseModify(cls):
        if sys.argv[1] not in ["-N", "-M", "-C", "-B"]:
            return None

        ret = DynObject()
        ret.new_profile_name = None
        ret.new_money = None
        ret.car_index = None
        ret.new_bounty = None
        ret.profile_name = None

        i = 1
        bFound = False
        while i < len(sys.argv):
            if sys.argv[i] == "-N":
                if ret.new_city_name is not None:
                    raise cls.ParseError('Error: Multiple "-N" arguments found.')
                if i + 1 >= len(sys.argv):
                    raise cls.ParseError('Error: New profile name must be specified after "-N" argument.')
                ret.new_profile_name = sys.argv[i + 1]
                i += 2
                bFound = True
                continue
            if sys.argv[i] == "-M":
                if ret.new_money is not None:
                    raise cls.ParseError('Error: Multiple "-M" arguments found.')
                if i + 1 >= len(sys.argv):
                    raise cls.ParseError('Error: New money value must be specified after "-M" argument.')
                try:
                    ret.new_money = int(sys.argv[i + 1])
                except ValueError:
                    raise cls.ParseError('Error: New money value must be integer.')
                i += 2
                bFound = True
                continue
            if sys.argv[i] == "-C":
                if ret.car_index is not None:
                    raise cls.ParseError('Error: Multiple "-C" arguments found.')
                if i + 1 >= len(sys.argv):
                    raise cls.ParseError('Error: Car index must be specified after "-C" argument.')
                ret.car_index = sys.argv[i + 1]
                i += 2
                bFound = True
                continue
            if sys.argv[i] == "-B":
                if ret.new_bounty is not None:
                    raise cls.ParseError('Error: Multiple "-B" arguments found.')
                if i + 1 >= len(sys.argv):
                    raise cls.ParseError('Error: New bounty value must be specified after "-B" argument.')
                try:
                    ret.new_bounty = int(sys.argv[i + 1])
                except ValueError:
                    raise cls.ParseError('Error: New bounty value must be integer.')
                i += 2
                bFound = True
                continue
            if ret.profile_name is None:
                ret.profile_name = sys.argv[i]
                i += 1
                continue
            break
        if i < len(sys.argv):
            raise cls.ParseError("Error: Redundant argument(s) found.")
        if not bFound:
            raise cls.ParseError("Error: No modify operation specified.")
        if ret.profile_name is None:
            raise cls.ParseError("Error: No profile specified.")
        if ret.new_bounty is not None:
            if ret.car_index is None:
                raise cls.ParseError("Error: No car index specified.")
        if ret.car_index is not None:
            if ret.new_bounty is None:
                raise cls.ParseError("Error: Car index is redundant.")
        return ret


class DynObject:
    pass


if __name__ == "__main__":
    op = None
    try:
        if len(sys.argv) <= 1:
            run()
            sys.exit(0)

        args = ArgParser.parseHelp()
        if args is not None:
            ArgParser.print_help()
            sys.exit(0)

        if op is None:
            args = ArgParser.parseShow()
            if args is not None:
                op = "show"
        if op is None:
            args = ArgParser.parseConfig()
            if args is not None:
                op = "config"
        if op is None:
            args = ArgParser.parseList()
            if args is not None:
                op = "list"
        if op is None:
            args = ArgParser.parseInspect()
            if args is not None:
                op = "inspect"
        if op is None:
            args = ArgParser.parseExportKeyMapping()
            if args is not None:
                op = "export-key-mapping"
        if op is None:
            args = ArgParser.parseModify()
            if args is not None:
                op = "modify"
        if op is None:
            raise ArgParser.ParseError('Argument(s) invalid.')
        edit(op, args)
    except ArgParser.ParseError as e:
        print(str(e) + ' Use "%s -h" to see usage information.' % (ArgParser.progName), file=sys.stderr)
        sys.exit(1)
